package com.inapp.ocreader;

import java.io.FileOutputStream;
import java.util.Calendar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.itwizard.mezzofanti.OCR;

public class OCReader extends Activity implements SurfaceHolder.Callback, View.OnClickListener, Runnable 
{

	// language files that are stored in "assets"	
	public static final String svLangExtNames[] = { ".DangAmbigs", ".freq-dawg", ".fst", ".inttemp", ".ngram_triv", 
		".normproto", ".pffmtable", ".unicharset", ".user-words", ".word-dawg"};	

	public static final String PACKAGE_NAME = "com.inapp.ocreader";
	public static final String DATA_PATH = "/sdcard/tessdata/";
	public static final String RESULTS_PATH = DATA_PATH + "out/";
	public static final String TEMP_PATH = DATA_PATH + "temp/";
	public static final String PACKAGE_DATA = "/data/app/" + PACKAGE_NAME + "-1.apk";	
	public static final String DOWNLOAD_URL = "http://www.itwizard.ro/mezzolang/";
	public static final String CONFIG_FILE = "config.txt";

	private boolean m_bHorizontalDisplay = true; 		// true=horizontal / false=vertical (this is updated all the time)	
	private Bitmap m_bmOCRBitmap; 						// bitmap we get the image from camera
	private boolean m_bHorizDispAtPicTaken = true;		// this is updated just before the picture taken, it will be sent as a param to the OCR processing
	private boolean m_bScreenRequestPicture = false;
	
	private static final String TAG = "OCReader.java";

	private boolean m_bHasSurface = false; 					// used to init the camera
	private boolean m_bSdcardMounted = true;				// checks if the sdcard is mounted or not
	private boolean m_bPreviewReady = false;    			// is the preview ready
	private boolean m_bFocusButtonPressed = false;			// focus button is pressed
	private ProgressDialog m_pdOCRInProgress;				// display this progress dialog while OCR runs
	//private OrientationEventListener m_OEListener = null;	// used to get vertical/horizontal camera position
	private CaptureLayout m_clCapture;						// Capture-mode	
	private boolean m_bOCRInProgress = false;				// if OCR is processing or not
	private boolean m_bLineMode = true;						// capture-mode: line/all
	private String m_sOCRResultLineMode = "";				// the ocr string in line mode
	
	public static boolean imageFromGallery = false;				// used to check if image is from gallery	
   public static String selectedImagePath = "";
   private int imgWidth, imgHeight;
   private	Bitmap gBitmap = null;
    
	// 'Menu' items
	private static final int PREFERENCES_GROUP_ID = 0;
	private static final int SETTINGS_ID = Menu.FIRST;
	private static final int GALLERY_ID = Menu.FIRST + 1;
	private static final int ABOUT_ID = Menu.FIRST + 2;
	private static final int SELECT_PICTURE = 1;
	
	private ImageView btSwitch;
	private ImageView btDelOne;
	private ImageView btGotoResults;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) 
	{
		super.onCreate(savedInstanceState);

		try
		{
			Log.v(TAG, "Starting app");
			this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
			requestWindowFeature(Window.FEATURE_NO_TITLE);
			getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
			Window window = getWindow();
			window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

			CameraManager.Initialize(getApplication());	        

			setContentView(R.layout.main);
			
			ImageView bt = (ImageView)findViewById(R.id.button_camerabutton);
			bt.setOnClickListener(new OnClickListener() {
				public void onClick(View v) {
					Log.v(TAG, "CameraButton OnClick");
					m_bScreenRequestPicture  = true;
					if(m_bSdcardMounted)
						RequestCameraFocus();
					else
						Toast.makeText(getBaseContext(), R.string.sdcard_unmount, Toast.LENGTH_LONG).show();
				}
			});
	
			m_clCapture = (CaptureLayout)findViewById(R.id.capturelayout_view);			
			
			m_bSdcardMounted = CheckSDCardState();

			SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
			OCR.mConfig.GetSettings(prefs);
			
			if (m_bLineMode)
				CameraManager.SetImgDivisor(2);
			else
				CameraManager.SetImgDivisor(OCR.mConfig.GetImgDivisor());

			m_bHasSurface = false;

			//CreateOrientationListener(this);
//			OrientationEnable(true);

			//RefreshStatusBar();

			if (m_bSdcardMounted && !AssetsManager.IsInstalled()) {
				StartInstallActivity();
			}

			m_MessageHandler.sendEmptyMessage(R.id.startCamera);

			CreateStatusbarButtonsCaptureMode();
			if (m_bLineMode)
				ShowLineModeButtons(true);
		}
		catch (Exception ex) {
			Log.e(TAG, "exception: onCreate():" + ex.toString());
		}
		catch (Throwable t) {
			Log.e(TAG, "exception: onCreate():" + t.toString());
		}
	}

	@Override
	protected void onPostResume() 
	{
		Log.v(TAG, "onPostResume()");
		super.onPostResume();
	}

	@Override  
	public void onDestroy() 
	{
		StopCamera();
//		OrientationEnable(false);
		OCR ocr = OCR.get();
		if (ocr != null)
			ocr.Destructor();
 		super.onDestroy();
		Log.d(TAG, "onDestroy() ENDING.");          
	}     

	@Override
	protected void onResume() 
	{
		super.onResume();
		Log.v(TAG, "onResume()");
		Log.v(TAG, "mconfig lang=" + OCR.mConfig.GetLanguageMore());


		m_bmOCRBitmap = null;
		gBitmap = null;
		System.gc();

		m_sOCRResultLineMode = "";

		imageFromGallery = false;
		m_bHorizDispAtPicTaken=true;
		m_bLineMode = true;
		m_clCapture.SetLineMode(m_bLineMode);		
		m_clCapture.SetText(m_sOCRResultLineMode);
		ShowLineModeButtons(true);

		RefreshStatusBar();
		m_bSdcardMounted = CheckSDCardState();      

		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);

		OCR.mConfig.GetSettings(prefs);
		
		if (m_bSdcardMounted && AssetsManager.IsInstalled())
		{
			OCR.Initialize();
			OCR.get().SetLanguage(OCR.mConfig.GetLanguage());
		}
		
		if (m_bLineMode)
			CameraManager.SetImgDivisor(2);
		else
			CameraManager.SetImgDivisor(OCR.mConfig.GetImgDivisor());

		m_MessageHandler.sendEmptyMessage(R.id.startCamera);

		SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
		SurfaceHolder surfaceHolder = surfaceView.getHolder();
		if (m_bHasSurface) {
			InitCamera(surfaceHolder);
		} else {
			surfaceHolder.addCallback(this);
			surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		}
	}

	@Override
	protected void onPause() 
	{
		StopCamera();
		super.onPause();
	} 

	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
	}

	public void surfaceCreated(SurfaceHolder holder) {
		Log.v(TAG, "surfaceCreated.");
		if (!m_bHasSurface) 
		{
			m_bHasSurface = true;
			SetCameraSurfaceHolder(holder);
			m_MessageHandler.sendEmptyMessage(R.id.startCamera);
			Log.v(TAG, "Call startCamera.");
		} 		
	}

	public void surfaceDestroyed(SurfaceHolder holder) 
	{
		m_bHasSurface = false;		
	}

	@Override
	public void onConfigurationChanged(Configuration newConfig) 
	{
		super.onConfigurationChanged(newConfig);
	}     

	/** MENU */
	@Override
	public boolean onCreateOptionsMenu(Menu menu) 
	{
		super.onCreateOptionsMenu(menu);

		menu.add(PREFERENCES_GROUP_ID, SETTINGS_ID, 0, R.string.menu_settings)
		.setIcon(android.R.drawable.ic_menu_preferences);
		menu.add(PREFERENCES_GROUP_ID, GALLERY_ID, 0, R.string.menu_gallery)
		.setIcon(android.R.drawable.ic_menu_gallery);		
		menu.add(PREFERENCES_GROUP_ID, ABOUT_ID, 0, R.string.menu_about)
		.setIcon(android.R.drawable.ic_menu_info_details);

		if (m_bSdcardMounted == false)
			menu.setGroupVisible(PREFERENCES_GROUP_ID, false);

		return true;
	} 

	@Override
	public boolean onOptionsItemSelected(MenuItem item) 
	{
		switch (item.getItemId()) {
		case SETTINGS_ID: {
			OCR.ReadAvailableLanguages();
			StopCamera();
			Intent intent = new Intent(Intent.ACTION_VIEW);
			intent.setClassName(this, PreferencesActivity.class.getName());
			startActivity(intent);
			break;
		}
		case GALLERY_ID:
			
            Intent intent = new Intent();
			Uri hacked_uri = Uri.parse("file://");
			intent.setDataAndType(hacked_uri, "image/*");
            intent.setType("image/*");
            intent.setAction(Intent.ACTION_GET_CONTENT);
            startActivityForResult(Intent.createChooser(intent,
                    "Select Picture"), SELECT_PICTURE);
            break;
		case ABOUT_ID:
			break;
		}
		return super.onOptionsItemSelected(item);
	}
	
	/** get the path of the image selected from the gallery */
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (resultCode == RESULT_OK) {
	        if (requestCode == SELECT_PICTURE) {
	        	
	        	Uri selectedImageUri = data.getData();

                //Image path from any File Manager
	        	String fileManagerImagePath = selectedImageUri.getPath();

                //Image path from Gallery
                String galleryImagePath = getPath(selectedImageUri);

                if(galleryImagePath!=null)
                	selectedImagePath = galleryImagePath;
                else 
                	selectedImagePath = fileManagerImagePath;

				finishActivity(SELECT_PICTURE);

            	Log.v(TAG, "Image path = " + selectedImagePath);
            	
	            m_MessageHandler.sendEmptyMessage(R.id.pictureAcquired);
   	        }
		}
	}
	
    public String getPath(Uri uri) {
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = managedQuery(uri, projection, null, null, null);
        if(cursor!=null)
        {
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
        }
        else return null;
    }

	private void SetCameraSurfaceHolder(SurfaceHolder surfaceHolder)
	{
		if (surfaceHolder == null || CameraManager.get() == null)
			return;

		CameraManager.get().SetSurfaceHolder(surfaceHolder);
	}

	private void InitCamera(SurfaceHolder surfaceHolder) 
	{
		if (CameraManager.get() == null)
			return;

		m_bPreviewReady = true;
		CameraManager.get().OpenDriver(surfaceHolder);
		CameraManager.get().StartPreview();		
	}

	private void InitCamera() 
	{
		Log.v(TAG, "InitCamera: start");		
		if (CameraManager.get() == null)
			return;

		Log.v(TAG, "InitCamera: OpenDriver");

		m_bPreviewReady = true;
		if (CameraManager.get().OpenDriver())
		{
			Log.v(TAG, "InitCamera: StartPreview");
			CameraManager.get().StartPreview();
		}
		Log.v(TAG, "InitCamera: end");
	}

	private void StopCamera()
	{
		CameraManager.get().StopPreview();
		CameraManager.get().CloseDriver();
		m_bPreviewReady = false;	
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) 
	{		
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

		switch (keyCode) 
		{
			case KeyEvent.KEYCODE_FOCUS:
			{
				if (event.getRepeatCount() == 0)
					return RequestCameraFocus();
				return true;
			}
			
			case KeyEvent.KEYCODE_CAMERA:
			{
				if (event.getRepeatCount() == 0)
					return RequestCameraTakePicture();
				return true;
			}
		}

		return super.onKeyDown(keyCode, event);
	}

	private boolean RequestCameraFocus()
	{
		String ss[] = OCR.getLanguagesNative();
		if (ss.length == 0)
		{
			ShowLanguageMissingAlertDialog();
			return false;
		}
				
		if (!m_bSdcardMounted)
			return false;
		if (m_bOCRInProgress == true)
			return false;

		m_bFocusButtonPressed = true;
		m_clCapture.DrawFocusIcon(true, m_bHorizontalDisplay);  
		CameraManager.get().RequestCameraFocus(m_MessageHandler);
		CameraManager.get().RequestAutoFocus();
		return true;
	}

	private boolean RequestCameraTakePicture()
	{
		if (!m_bSdcardMounted)
			return false;
		if (m_bOCRInProgress == true)
			return false;

		m_bOCRInProgress = true;
		if (m_bPreviewReady)
		{
			m_bHorizDispAtPicTaken = m_bHorizontalDisplay;

			CompareTime(TAG + "request a picture");
			m_clCapture.DrawFocused(false, false);
			m_clCapture.DrawFocusIcon(false, m_bHorizontalDisplay);
			CameraManager.get().RequestPicture(m_MessageHandler);
			CameraManager.get().GetPicture();
			if (m_bLineMode)
				m_clCapture.ShowWaiting(getString(R.string.capturelayout_takingpicture));
			
			return true;
		}
		return false;
	}
	
	@Override
	public boolean onKeyUp(int keyCode, KeyEvent event) 
	{
		switch (keyCode) {
		case KeyEvent.KEYCODE_FOCUS:
			m_bFocusButtonPressed = false;
			m_clCapture.DrawFocusIcon(false, m_bHorizontalDisplay);
			m_clCapture.DrawFocused(false, false);
			return true;
		}
		return super.onKeyUp(keyCode, event);
	}

	public void onClick(View arg0) {
	} 	

	public void DoOCRJob(Bitmap bm)
	{    	
		Log.v(TAG, "DoOCRJob()-------------");
		m_bmOCRBitmap = bm;

		if (bm == null)
			return;

		if (!m_bLineMode)
		{
			m_pdOCRInProgress = ProgressDialog.show(this, this.getString(R.string.ocr_processing_title), 
					this.getString(R.string.ocr_processing_body_begin) +" "+ OCR.mConfig.GetLanguageMore() + " " + this.getString(R.string.ocr_processing_body_end), 
					true, true);
			m_pdOCRInProgress.setOnCancelListener( new OnCancelListener() {
				public void onCancel(DialogInterface dialog) 
				{
					android.os.Process.killProcess(android.os.Process.myPid());
				}    		    		
			});
		}
		else
		{
			m_clCapture.ShowWaiting(getString(R.string.capturelayout_processing) + " " +
					OCR.mConfig.GetLanguageMore() + " " + 
					getString(R.string.capturelayout_processing2));    		
		}

		Thread theOCRthread = new Thread(this);
		theOCRthread.start();
	}

	/** start the OCR thread */
	public void run() 
	{
		CompareTime(TAG + " STARTING ocr processing");

		// called by the OCR thread
		int iPicWidth  = m_bmOCRBitmap.getWidth();
		int iPicHeight = m_bmOCRBitmap.getHeight();
		int[] iImage = null;

		try
		{
			iImage = new int[iPicWidth * iPicHeight];
			Log.v(TAG, "allocated img buffer: " +iPicWidth + ", "+iPicHeight);
			m_bmOCRBitmap.getPixels(iImage, 0, iPicWidth, 0, 0, iPicWidth, iPicHeight);
			Log.v(TAG, "pix1="+Integer.toHexString(iImage[0]));
		}
		catch (Exception ex)
		{
			Log.v(TAG, "exception: run():" + ex.toString());
			m_bmOCRBitmap = null;
			System.gc();			
		}


		if (iImage != null)
		{
			String m_sOCRResult = OCR.get().ImgOCRAndFilter(iImage, iPicWidth, iPicHeight, m_bHorizDispAtPicTaken, m_bLineMode);			
			Log.v(TAG, "ocr done text= [" + m_sOCRResult +"]");
			iImage = null;
			m_bmOCRBitmap = null;
			System.gc();			

			OCR.get().SaveMeanConfidence();

			Log.v(TAG, "starting results handler");
		}
		else
		{
			System.gc();
			m_bOCRInProgress = false;
			m_MessageHandler.sendEmptyMessage(R.id.restartCaptureMode);
			return;
		}

		m_MessageHandler.sendEmptyMessage(R.id.ocrFinished);
		Log.i(TAG, "pcjpg - finish startPreview()");

		CompareTime(TAG + "finished the ocr processing");
	} 

	private Handler m_MessageHandler = new Handler() 
	{
		@Override
		public void handleMessage(Message msg) 
		{
			switch(msg.what)
			{
			case R.id.installactivity_killApp:
				Log.v(TAG, "Killed by installer.");
				android.os.Process.killProcess(android.os.Process.myPid());
				break;
				//----------------------------------------------------------------------------
			case R.id.pictureAcquired:
				Log.v(TAG, "OCRing Image from gallery-----------");

				Log.v(TAG, "Image Path" + selectedImagePath);
				//do OCR on image from gallery
				System.gc();
				
				imageFromGallery = true;
				
				try {
					BitmapFactory.Options options = new BitmapFactory.Options();
					options.inTempStorage = new byte[16*1024];
					options.inSampleSize = 2;

					gBitmap = BitmapFactory.decodeFile(selectedImagePath, options);
					
				} catch(Throwable th) {
					Log.v(TAG, "exception: handler-galPicAcq: "+ th.toString());
					m_bOCRInProgress = false;
					if (m_bLineMode)
						m_clCapture.ShowWaiting("");
					else
						m_MessageHandler.sendEmptyMessage(R.id.restartCaptureMode);
					break;
				}

				CompareTime(TAG + "starting the thread");
				
				System.gc();
				
				m_bLineMode = false;
				m_bHorizDispAtPicTaken = true;
				
				OCR.Initialize();				
				OCR.get().SetLanguage(OCR.mConfig.GetLanguage());
				
				imgWidth  = gBitmap.getWidth();
				imgHeight = gBitmap.getHeight();
				//int bpp = gBitmap.getRowBytes();
				//String text = OCR.get().FileOCR(selectedImagePath,picWidth,picHeight,bpp);
				//Log.i(TAG, text);

				DoOCRJob(gBitmap);
												
	            break;
				//----------------------------------------------------------------------------
			case R.id.restartCaptureMode:
       		

				m_bmOCRBitmap = null;
				System.gc();

				if (m_bLineMode)
					m_clCapture.ShowWaiting("");    		
				else
					m_pdOCRInProgress.dismiss();

				break;
				//----------------------------------------------------------------------------
			case R.id.startCamera:
				InitCamera();
				if (!m_bSdcardMounted)
					Toast.makeText(getBaseContext(), R.string.sdcard_unmount, Toast.LENGTH_SHORT).show();
				break;
				//----------------------------------------------------------------------------
			case R.id.cameramanager_requestpicture:

				Log.v(TAG, "handleMessage() R.id.decode");
				CompareTime(TAG + "in handler, just received the picture");

				// do ocr
				Bitmap mBitmap = null;
				try
				{
					// save the file on disk
					FileOutputStream fs = new FileOutputStream(RESULTS_PATH + "img.jpg");
					fs.write((byte[])msg.obj, 0, ((byte[]) msg.obj).length);
					fs.close();

					mBitmap = BitmapFactory.decodeByteArray((byte[]) msg.obj, 0, ((byte[]) msg.obj).length);
					msg.obj = null;
					System.gc();
					
					Log.v(TAG, "w="+mBitmap.getWidth() + " h="+mBitmap.getHeight());
					if (m_bLineMode) // we crop just the image of interest
						mBitmap = Bitmap.createBitmap(mBitmap, 256, 768/2-30, 512, 60, null, false);
					// otherwise, we use all image
				}
				catch (Throwable th) 
				{
					Log.v(TAG, "exception: handler-cmrequestpic: "+ th.toString());
					m_bOCRInProgress = false;
					if (m_bLineMode)
						m_clCapture.ShowWaiting("");
					else
						m_MessageHandler.sendEmptyMessage(R.id.restartCaptureMode);
					break;
				}


				CompareTime(TAG + "starting the thread");
								
				OCR.Initialize();				
				OCR.get().SetLanguage(OCR.mConfig.GetLanguage());
				
				DoOCRJob(mBitmap);

				break;
				//----------------------------------------------------------------------------
			case R.id.ocrFinished:
				m_bOCRInProgress = false;
				if (!m_bLineMode)
				{
					m_pdOCRInProgress.dismiss();
					System.gc();

					StopCamera();
					StartResultsActivity();
				}
				else
				{
					Log.v(TAG, "before processing results");
					String padding = " ";
					if (m_sOCRResultLineMode.length() == 0)
						padding = "";

					String s = OCR.m_ssOCRResult.toString().replaceAll("[\r\n]+", "");
					while (s.length()>0 && s.charAt(0) == ' ')
						s = s.substring(1);
					while (s.length()>0 && s.charAt(s.length()-1) == ' ')
						s = s.substring(0, s.length()-1);

					m_sOCRResultLineMode = m_sOCRResultLineMode.concat(padding + s);

					m_clCapture.ShowWaiting("");
					m_clCapture.SetText(m_sOCRResultLineMode);
				}
				OCR.get().OCRClean();
				break;
				//----------------------------------------------------------------------------
			case R.id.cameramanager_focus_succeded:
				if (!m_bFocusButtonPressed)
					return;				
				m_clCapture.DrawFocused(true, true);
				PlaySoundOnFocus();
				
				if (m_bScreenRequestPicture)
					RequestCameraTakePicture();
				m_bScreenRequestPicture = false;
				break;
				//----------------------------------------------------------------------------
			case R.id.cameramanager_focus_failed:
				if (!m_bFocusButtonPressed)
					return;				
				m_clCapture.DrawFocused(true, false);
				Vibrate();
				m_bScreenRequestPicture = false;
				break;		
				//----------------------------------------------------------------------------
			default:
				break;

			}

			super.handleMessage(msg);
		}

	};

	private void ShowLanguageMissingAlertDialog()
	{
		AlertDialog.Builder builderH = new AlertDialog.Builder(this);
		builderH.setIcon(android.R.drawable.ic_dialog_alert);
		builderH.setTitle(getString(R.string.nolanginstalled_title));
		builderH.setMessage(getString(R.string.nolanginstalled_body));
		builderH.setPositiveButton("Ok", null);
		builderH.show();					
	}

	private void StartResultsActivity()
	{
		if (m_bSdcardMounted) 
		{
			Intent intent = new Intent(Intent.ACTION_VIEW);
			Bundle bun = new Bundle();
			// if not in line-mode, the activity will get the results directly from the OCR results
			bun.putInt("imgWidth", imgWidth);    		
			bun.putInt("imgHeight", imgHeight);    				
			bun.putString("LineModeText", m_sOCRResultLineMode);
			bun.putBoolean("bLineMode", m_bLineMode);
			intent.putExtras(bun);
			intent.setClassName(this, ResultsActivity.class.getName());
			startActivity(intent); 
		}		
	}

	private void StartInstallActivity()
	{
		Log.v(TAG,"Starting InstallActivity() ------");
		// install the languages if needed, create directory structure (one time)
		Intent intent = new Intent(Intent.ACTION_VIEW);
		InstallActivity.SetParentMessageHandler(m_MessageHandler);
		intent.setClassName(this, InstallActivity.class.getName());
		startActivity(intent);	
	}

	public static boolean CheckSDCardState()
	{
		boolean ret = true;
		String sdcardState = Environment.getExternalStorageState();
		if (sdcardState.compareTo(Environment.MEDIA_MOUNTED) != 0)
		{
			Log.v(TAG, "error: sdcard not mounted! [" + sdcardState + "]"); 
			ret = false;
		}
		return ret;
	}
/*
	private void CreateOrientationListener(Context context)
	{
		m_OEListener = new OrientationEventListener (context, SensorManager.SENSOR_DELAY_UI)    	
		{
			public void onOrientationChanged (int orientation) 
			{
				if (m_bSdcardMounted == false)
					return;

				if ((orientation >= 0 && orientation <= 10 ) || (orientation >= 350 && orientation <= 360 ))
				{
					if (m_bHorizontalDisplay) {
						m_bHorizontalDisplay = false;
					}
				}
				else {
					if (orientation >= 260 && orientation <= 280 )
					{
						if (!m_bHorizontalDisplay)
						{
							m_bHorizontalDisplay = true;
						}
					}
				}
			}
		};
	}

	public void OrientationEnable(boolean enable) 
	{
		if (m_OEListener==null)
			return;

		if (enable)
			m_OEListener.enable();
		else
			m_OEListener.disable();
	}
*/
	private void RefreshStatusBar()
	{
		TextView tbox = (TextView) findViewById(R.id.status_text_view);
		if (!m_bLineMode) {
			tbox.setText("\t" + getString(R.string.capturemode_statustext_switchtosmall) );        	        	
		}
		else {
			tbox.setText("\t" + getString(R.string.capturemode_statustext_switchtolarge));
		}
	}

	private void PlaySoundOnFocus()
	{
		ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_SYSTEM, 100);
		tg.startTone(ToneGenerator.TONE_PROP_BEEP2);
	}

	private void Vibrate()
	{
		Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
		vibrator.vibrate(200);
	}

	private static long m_lTime = 0;
	
	public static void CompareTime(String status)
	{
		long prevtime = m_lTime;
		Calendar now = Calendar.getInstance();
		long currenttime=now.getTimeInMillis();

		Log.v(TAG, "Status: "+status);
		Log.v(TAG, "Compare prev="+m_lTime + " to current=" + currenttime + " diff=" + (currenttime-prevtime));
		m_lTime = currenttime;
	}

	private void CreateStatusbarButtonsCaptureMode()
	{
		btSwitch = (ImageView) findViewById(R.id.button_switch);
		btDelOne = (ImageView) findViewById(R.id.button_delone);
		btGotoResults = (ImageView) findViewById(R.id.button_gotoresults);

		btSwitch.setOnClickListener(new OnClickListener() 
		{
			public void onClick(View clickedView) 
			{
				Log.v(TAG, "switch button: onClick line_mode = " + m_bLineMode);
				m_bLineMode = !m_bLineMode;
				m_clCapture.SetLineMode(m_bLineMode);

				RefreshStatusBar();

				if (m_bLineMode)
				{
					CameraManager.SetImgDivisor(2);
					CameraManager.get().SetCameraParameters();
					ShowLineModeButtons(true);
				}
				else
				{
					CameraManager.SetImgDivisor(OCR.mConfig.GetImgDivisor());
					CameraManager.get().SetCameraParameters();
					ShowLineModeButtons(false);
					m_sOCRResultLineMode = "";
					m_clCapture.SetText("");
				}
			}
		});

		btDelOne.setOnClickListener(new OnClickListener() 
		{
			public void onClick(View clickedView) 
			{
				Log.v(TAG, "m_btDelOne: onClick line_mode = " + m_bLineMode);
				int iLastSpace = m_sOCRResultLineMode.lastIndexOf(' ');
				if (iLastSpace <= 0)
					m_sOCRResultLineMode = "";
				else
					m_sOCRResultLineMode = m_sOCRResultLineMode.substring(0, iLastSpace);
				m_clCapture.SetText(m_sOCRResultLineMode);			
			}
		});

		btGotoResults.setOnClickListener(new OnClickListener() 
		{
			public void onClick(View clickedView) 
			{
				Log.v(TAG, "m_btGotoResults: onClick line_mode = " + m_bLineMode);
				StartResultsActivity();				
				System.gc();
			}
		});
	}

	private void ShowLineModeButtons(boolean val)
	{
		if (val)
		{
			btDelOne.setVisibility(View.VISIBLE);
			btGotoResults.setVisibility(View.VISIBLE);
		}
		else
		{
			btDelOne.setVisibility(View.GONE);
			btGotoResults.setVisibility(View.GONE);
		}  
		m_clCapture.invalidate();
	}

}